﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using UniRx.InternalUtil;
using UnityEngine;

namespace UniRx
{
	// Token: 0x0200037C RID: 892
	public static class Scheduler
	{
		// Token: 0x1700010D RID: 269
		// (get) Token: 0x0600122A RID: 4650 RVA: 0x00052F6F File Offset: 0x0005136F
		public static bool IsCurrentThreadSchedulerScheduleRequired
		{
			get
			{
				return Scheduler.CurrentThreadScheduler.IsScheduleRequired;
			}
		}

		// Token: 0x1700010E RID: 270
		// (get) Token: 0x0600122B RID: 4651 RVA: 0x00052F76 File Offset: 0x00051376
		public static DateTimeOffset Now
		{
			get
			{
				return DateTimeOffset.UtcNow;
			}
		}

		// Token: 0x0600122C RID: 4652 RVA: 0x00052F7D File Offset: 0x0005137D
		public static TimeSpan Normalize(TimeSpan timeSpan)
		{
			return (!(timeSpan >= TimeSpan.Zero)) ? TimeSpan.Zero : timeSpan;
		}

		// Token: 0x0600122D RID: 4653 RVA: 0x00052F9A File Offset: 0x0005139A
		public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action action)
		{
			return scheduler.Schedule(dueTime - scheduler.Now, action);
		}

		// Token: 0x0600122E RID: 4654 RVA: 0x00052FB0 File Offset: 0x000513B0
		public static IDisposable Schedule(this IScheduler scheduler, Action<Action> action)
		{
			CompositeDisposable group = new CompositeDisposable(1);
			object gate = new object();
			Action recursiveAction = null;
			recursiveAction = delegate()
			{
				action(delegate
				{
					bool isAdded = false;
					bool isDone = false;
					IDisposable d = null;
					object gate=null;
					d = scheduler.Schedule(delegate()
					{
						object gate2 = gate;
						lock (gate2)
						{
							if (isAdded)
							{
								group.Remove(d);
							}
							else
							{
								isDone = true;
							}
						}
						recursiveAction();
					});
					gate = gate;
					lock (gate)
					{
						if (!isDone)
						{
							group.Add(d);
							isAdded = true;
						}
					}
				});
			};
			group.Add(scheduler.Schedule(recursiveAction));
			return group;
		}

		// Token: 0x0600122F RID: 4655 RVA: 0x00053024 File Offset: 0x00051424
		public static IDisposable Schedule(this IScheduler scheduler, TimeSpan dueTime, Action<Action<TimeSpan>> action)
		{
			CompositeDisposable group = new CompositeDisposable(1);
			object gate = new object();
			Action recursiveAction = null;
			recursiveAction = delegate()
			{
				action(delegate(TimeSpan dt)
				{
					bool isAdded = false;
					bool isDone = false;
					IDisposable d = null;
					object gate=null;
					d = scheduler.Schedule(dt, delegate()
					{
						object gate2 = gate;
						lock (gate2)
						{
							if (isAdded)
							{
								group.Remove(d);
							}
							else
							{
								isDone = true;
							}
						}
						recursiveAction();
					});
					gate = gate;
					lock (gate)
					{
						if (!isDone)
						{
							group.Add(d);
							isAdded = true;
						}
					}
				});
			};
			group.Add(scheduler.Schedule(dueTime, recursiveAction));
			return group;
		}

		// Token: 0x06001230 RID: 4656 RVA: 0x00053098 File Offset: 0x00051498
		public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action<Action<DateTimeOffset>> action)
		{
			CompositeDisposable group = new CompositeDisposable(1);
			object gate = new object();
			Action recursiveAction = null;
			recursiveAction = delegate()
			{
				action(delegate(DateTimeOffset dt)
				{
					bool isAdded = false;
					bool isDone = false;
					IDisposable d = null;
					object gate=null;
					d = scheduler.Schedule(dt, delegate()
					{
						object gate2 = gate;
						lock (gate2)
						{
							if (isAdded)
							{
								group.Remove(d);
							}
							else
							{
								isDone = true;
							}
						}
						recursiveAction();
					});
					gate = gate;
					lock (gate)
					{
						if (!isDone)
						{
							group.Add(d);
							isAdded = true;
						}
					}
				});
			};
			group.Add(scheduler.Schedule(dueTime, recursiveAction));
			return group;
		}

		// Token: 0x06001231 RID: 4657 RVA: 0x0005310C File Offset: 0x0005150C
		public static void SetDefaultForUnity()
		{
			Scheduler.DefaultSchedulers.ConstantTimeOperations = Scheduler.Immediate;
			Scheduler.DefaultSchedulers.TailRecursion = Scheduler.Immediate;
			Scheduler.DefaultSchedulers.Iteration = Scheduler.CurrentThread;
			Scheduler.DefaultSchedulers.TimeBasedOperations = Scheduler.MainThread;
			Scheduler.DefaultSchedulers.AsyncConversions = Scheduler.ThreadPool;
		}

		// Token: 0x1700010F RID: 271
		// (get) Token: 0x06001232 RID: 4658 RVA: 0x00053140 File Offset: 0x00051540
		public static IScheduler MainThread
		{
			get
			{
				IScheduler result;
				if ((result = Scheduler.mainThread) == null)
				{
					result = (Scheduler.mainThread = new Scheduler.MainThreadScheduler());
				}
				return result;
			}
		}

		// Token: 0x17000110 RID: 272
		// (get) Token: 0x06001233 RID: 4659 RVA: 0x00053159 File Offset: 0x00051559
		public static IScheduler MainThreadIgnoreTimeScale
		{
			get
			{
				IScheduler result;
				if ((result = Scheduler.mainThreadIgnoreTimeScale) == null)
				{
					result = (Scheduler.mainThreadIgnoreTimeScale = new Scheduler.IgnoreTimeScaleMainThreadScheduler());
				}
				return result;
			}
		}

		// Token: 0x17000111 RID: 273
		// (get) Token: 0x06001234 RID: 4660 RVA: 0x00053172 File Offset: 0x00051572
		public static IScheduler MainThreadFixedUpdate
		{
			get
			{
				IScheduler result;
				if ((result = Scheduler.mainThreadFixedUpdate) == null)
				{
					result = (Scheduler.mainThreadFixedUpdate = new Scheduler.FixedUpdateMainThreadScheduler());
				}
				return result;
			}
		}

		// Token: 0x17000112 RID: 274
		// (get) Token: 0x06001235 RID: 4661 RVA: 0x0005318B File Offset: 0x0005158B
		public static IScheduler MainThreadEndOfFrame
		{
			get
			{
				IScheduler result;
				if ((result = Scheduler.mainThreadEndOfFrame) == null)
				{
					result = (Scheduler.mainThreadEndOfFrame = new Scheduler.EndOfFrameMainThreadScheduler());
				}
				return result;
			}
		}

		// Token: 0x04000AF7 RID: 2807
		public static readonly IScheduler CurrentThread = new Scheduler.CurrentThreadScheduler();

		// Token: 0x04000AF8 RID: 2808
		public static readonly IScheduler Immediate = new Scheduler.ImmediateScheduler();

		// Token: 0x04000AF9 RID: 2809
		public static readonly IScheduler ThreadPool = new Scheduler.ThreadPoolScheduler();

		// Token: 0x04000AFA RID: 2810
		private static IScheduler mainThread;

		// Token: 0x04000AFB RID: 2811
		private static IScheduler mainThreadIgnoreTimeScale;

		// Token: 0x04000AFC RID: 2812
		private static IScheduler mainThreadFixedUpdate;

		// Token: 0x04000AFD RID: 2813
		private static IScheduler mainThreadEndOfFrame;

		// Token: 0x0200037D RID: 893
		private class CurrentThreadScheduler : IScheduler
		{
			// Token: 0x06001238 RID: 4664 RVA: 0x000531CC File Offset: 0x000515CC
			private static SchedulerQueue GetQueue()
			{
				return Scheduler.CurrentThreadScheduler.s_threadLocalQueue;
			}

			// Token: 0x06001239 RID: 4665 RVA: 0x000531D3 File Offset: 0x000515D3
			private static void SetQueue(SchedulerQueue newQueue)
			{
				Scheduler.CurrentThreadScheduler.s_threadLocalQueue = newQueue;
			}

			// Token: 0x17000113 RID: 275
			// (get) Token: 0x0600123A RID: 4666 RVA: 0x000531DB File Offset: 0x000515DB
			private static TimeSpan Time
			{
				get
				{
					if (Scheduler.CurrentThreadScheduler.s_clock == null)
					{
						Scheduler.CurrentThreadScheduler.s_clock = Stopwatch.StartNew();
					}
					return Scheduler.CurrentThreadScheduler.s_clock.Elapsed;
				}
			}

			// Token: 0x17000114 RID: 276
			// (get) Token: 0x0600123B RID: 4667 RVA: 0x000531FB File Offset: 0x000515FB
			[EditorBrowsable(EditorBrowsableState.Advanced)]
			public static bool IsScheduleRequired
			{
				get
				{
					return Scheduler.CurrentThreadScheduler.GetQueue() == null;
				}
			}

			// Token: 0x0600123C RID: 4668 RVA: 0x00053205 File Offset: 0x00051605
			public IDisposable Schedule(Action action)
			{
				return this.Schedule(TimeSpan.Zero, action);
			}

			// Token: 0x0600123D RID: 4669 RVA: 0x00053214 File Offset: 0x00051614
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				if (action == null)
				{
					throw new ArgumentNullException("action");
				}
				TimeSpan dueTime2 = Scheduler.CurrentThreadScheduler.Time + Scheduler.Normalize(dueTime);
				ScheduledItem scheduledItem = new ScheduledItem(action, dueTime2);
				SchedulerQueue schedulerQueue = Scheduler.CurrentThreadScheduler.GetQueue();
				if (schedulerQueue == null)
				{
					schedulerQueue = new SchedulerQueue(4);
					schedulerQueue.Enqueue(scheduledItem);
					Scheduler.CurrentThreadScheduler.SetQueue(schedulerQueue);
					try
					{
						Scheduler.CurrentThreadScheduler.Trampoline.Run(schedulerQueue);
					}
					finally
					{
						Scheduler.CurrentThreadScheduler.SetQueue(null);
					}
				}
				else
				{
					schedulerQueue.Enqueue(scheduledItem);
				}
				return scheduledItem.Cancellation;
			}

			// Token: 0x17000115 RID: 277
			// (get) Token: 0x0600123E RID: 4670 RVA: 0x000532A0 File Offset: 0x000516A0
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x04000AFE RID: 2814
			[ThreadStatic]
			private static SchedulerQueue s_threadLocalQueue;

			// Token: 0x04000AFF RID: 2815
			[ThreadStatic]
			private static Stopwatch s_clock;

			// Token: 0x0200037E RID: 894
			private static class Trampoline
			{
				// Token: 0x0600123F RID: 4671 RVA: 0x000532A8 File Offset: 0x000516A8
				public static void Run(SchedulerQueue queue)
				{
					while (queue.Count > 0)
					{
						ScheduledItem scheduledItem = queue.Dequeue();
						if (!scheduledItem.IsCanceled)
						{
							TimeSpan timeout = scheduledItem.DueTime - Scheduler.CurrentThreadScheduler.Time;
							if (timeout.Ticks > 0L)
							{
								Thread.Sleep(timeout);
							}
							if (!scheduledItem.IsCanceled)
							{
								scheduledItem.Invoke();
							}
						}
					}
				}
			}
		}

		// Token: 0x02000383 RID: 899
		private class ImmediateScheduler : IScheduler
		{
			// Token: 0x17000117 RID: 279
			// (get) Token: 0x06001247 RID: 4679 RVA: 0x00053316 File Offset: 0x00051716
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x06001248 RID: 4680 RVA: 0x0005331D File Offset: 0x0005171D
			public IDisposable Schedule(Action action)
			{
				action();
				return Disposable.Empty;
			}

			// Token: 0x06001249 RID: 4681 RVA: 0x0005332C File Offset: 0x0005172C
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				TimeSpan timeout = Scheduler.Normalize(dueTime);
				if (timeout.Ticks > 0L)
				{
					Thread.Sleep(timeout);
				}
				action();
				return Disposable.Empty;
			}
		}

		// Token: 0x02000384 RID: 900
		public static class DefaultSchedulers
		{
			// Token: 0x17000118 RID: 280
			// (get) Token: 0x0600124A RID: 4682 RVA: 0x0005335F File Offset: 0x0005175F
			// (set) Token: 0x0600124B RID: 4683 RVA: 0x00053378 File Offset: 0x00051778
			public static IScheduler ConstantTimeOperations
			{
				get
				{
					IScheduler result;
					if ((result = Scheduler.DefaultSchedulers.constantTime) == null)
					{
						result = (Scheduler.DefaultSchedulers.constantTime = Scheduler.Immediate);
					}
					return result;
				}
				set
				{
					Scheduler.DefaultSchedulers.constantTime = value;
				}
			}

			// Token: 0x17000119 RID: 281
			// (get) Token: 0x0600124C RID: 4684 RVA: 0x00053380 File Offset: 0x00051780
			// (set) Token: 0x0600124D RID: 4685 RVA: 0x00053399 File Offset: 0x00051799
			public static IScheduler TailRecursion
			{
				get
				{
					IScheduler result;
					if ((result = Scheduler.DefaultSchedulers.tailRecursion) == null)
					{
						result = (Scheduler.DefaultSchedulers.tailRecursion = Scheduler.Immediate);
					}
					return result;
				}
				set
				{
					Scheduler.DefaultSchedulers.tailRecursion = value;
				}
			}

			// Token: 0x1700011A RID: 282
			// (get) Token: 0x0600124E RID: 4686 RVA: 0x000533A1 File Offset: 0x000517A1
			// (set) Token: 0x0600124F RID: 4687 RVA: 0x000533BA File Offset: 0x000517BA
			public static IScheduler Iteration
			{
				get
				{
					IScheduler result;
					if ((result = Scheduler.DefaultSchedulers.iteration) == null)
					{
						result = (Scheduler.DefaultSchedulers.iteration = Scheduler.CurrentThread);
					}
					return result;
				}
				set
				{
					Scheduler.DefaultSchedulers.iteration = value;
				}
			}

			// Token: 0x1700011B RID: 283
			// (get) Token: 0x06001250 RID: 4688 RVA: 0x000533C2 File Offset: 0x000517C2
			// (set) Token: 0x06001251 RID: 4689 RVA: 0x000533DB File Offset: 0x000517DB
			public static IScheduler TimeBasedOperations
			{
				get
				{
					IScheduler result;
					if ((result = Scheduler.DefaultSchedulers.timeBasedOperations) == null)
					{
						result = (Scheduler.DefaultSchedulers.timeBasedOperations = Scheduler.MainThread);
					}
					return result;
				}
				set
				{
					Scheduler.DefaultSchedulers.timeBasedOperations = value;
				}
			}

			// Token: 0x1700011C RID: 284
			// (get) Token: 0x06001252 RID: 4690 RVA: 0x000533E3 File Offset: 0x000517E3
			// (set) Token: 0x06001253 RID: 4691 RVA: 0x000533FC File Offset: 0x000517FC
			public static IScheduler AsyncConversions
			{
				get
				{
					IScheduler result;
					if ((result = Scheduler.DefaultSchedulers.asyncConversions) == null)
					{
						result = (Scheduler.DefaultSchedulers.asyncConversions = Scheduler.ThreadPool);
					}
					return result;
				}
				set
				{
					Scheduler.DefaultSchedulers.asyncConversions = value;
				}
			}

			// Token: 0x06001254 RID: 4692 RVA: 0x00053404 File Offset: 0x00051804
			public static void SetDotNetCompatible()
			{
				Scheduler.DefaultSchedulers.ConstantTimeOperations = Scheduler.Immediate;
				Scheduler.DefaultSchedulers.TailRecursion = Scheduler.Immediate;
				Scheduler.DefaultSchedulers.Iteration = Scheduler.CurrentThread;
				Scheduler.DefaultSchedulers.TimeBasedOperations = Scheduler.ThreadPool;
				Scheduler.DefaultSchedulers.AsyncConversions = Scheduler.ThreadPool;
			}

			// Token: 0x04000B00 RID: 2816
			private static IScheduler constantTime;

			// Token: 0x04000B01 RID: 2817
			private static IScheduler tailRecursion;

			// Token: 0x04000B02 RID: 2818
			private static IScheduler iteration;

			// Token: 0x04000B03 RID: 2819
			private static IScheduler timeBasedOperations;

			// Token: 0x04000B04 RID: 2820
			private static IScheduler asyncConversions;
		}

		// Token: 0x02000385 RID: 901
		private class ThreadPoolScheduler : IScheduler, ISchedulerPeriodic, ISchedulerQueueing
		{
			// Token: 0x1700011D RID: 285
			// (get) Token: 0x06001256 RID: 4694 RVA: 0x00053440 File Offset: 0x00051840
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x06001257 RID: 4695 RVA: 0x00053448 File Offset: 0x00051848
			public IDisposable Schedule(Action action)
			{
				BooleanDisposable d = new BooleanDisposable();
				System.Threading.ThreadPool.QueueUserWorkItem(delegate(object _)
				{
					if (!d.IsDisposed)
					{
						action();
					}
				});
				return d;
			}

			// Token: 0x06001258 RID: 4696 RVA: 0x00053485 File Offset: 0x00051885
			public IDisposable Schedule(DateTimeOffset dueTime, Action action)
			{
				return this.Schedule(dueTime - this.Now, action);
			}

			// Token: 0x06001259 RID: 4697 RVA: 0x0005349A File Offset: 0x0005189A
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				return new Scheduler.ThreadPoolScheduler.Timer(dueTime, action);
			}

			// Token: 0x0600125A RID: 4698 RVA: 0x000534A3 File Offset: 0x000518A3
			public IDisposable SchedulePeriodic(TimeSpan period, Action action)
			{
				return new Scheduler.ThreadPoolScheduler.PeriodicTimer(period, action);
			}

			// Token: 0x0600125B RID: 4699 RVA: 0x000534AC File Offset: 0x000518AC
			public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
			{
				System.Threading.ThreadPool.QueueUserWorkItem(delegate(object callBackState)
				{
					if (!cancel.IsDisposed)
					{
						action((T)((object)callBackState));
					}
				}, state);
			}

			// Token: 0x02000386 RID: 902
			private sealed class Timer : IDisposable
			{
				// Token: 0x0600125C RID: 4700 RVA: 0x000534E8 File Offset: 0x000518E8
				public Timer(TimeSpan dueTime, Action action)
				{
					this._disposable = new SingleAssignmentDisposable();
					this._disposable.Disposable = Disposable.Create(new Action(this.Unroot));
					this._action = action;
					this._timer = new System.Threading.Timer(new TimerCallback(this.Tick), null, dueTime, TimeSpan.FromMilliseconds(-1.0));
					object obj = Scheduler.ThreadPoolScheduler.Timer.s_timers;
					lock (obj)
					{
						if (!this._hasRemoved)
						{
							Scheduler.ThreadPoolScheduler.Timer.s_timers.Add(this._timer);
							this._hasAdded = true;
						}
					}
				}

				// Token: 0x0600125D RID: 4701 RVA: 0x0005359C File Offset: 0x0005199C
				private void Tick(object state)
				{
					try
					{
						if (!this._disposable.IsDisposed)
						{
							this._action();
						}
					}
					finally
					{
						this.Unroot();
					}
				}

				// Token: 0x0600125E RID: 4702 RVA: 0x000535E0 File Offset: 0x000519E0
				private void Unroot()
				{
					this._action = Stubs.Nop;
					System.Threading.Timer timer = null;
					object obj = Scheduler.ThreadPoolScheduler.Timer.s_timers;
					lock (obj)
					{
						if (!this._hasRemoved)
						{
							timer = this._timer;
							this._timer = null;
							if (this._hasAdded && timer != null)
							{
								Scheduler.ThreadPoolScheduler.Timer.s_timers.Remove(timer);
							}
							this._hasRemoved = true;
						}
					}
					if (timer != null)
					{
						timer.Dispose();
					}
				}

				// Token: 0x0600125F RID: 4703 RVA: 0x0005366C File Offset: 0x00051A6C
				public void Dispose()
				{
					this._disposable.Dispose();
				}

				// Token: 0x04000B05 RID: 2821
				private static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();

				// Token: 0x04000B06 RID: 2822
				private readonly SingleAssignmentDisposable _disposable;

				// Token: 0x04000B07 RID: 2823
				private Action _action;

				// Token: 0x04000B08 RID: 2824
				private System.Threading.Timer _timer;

				// Token: 0x04000B09 RID: 2825
				private bool _hasAdded;

				// Token: 0x04000B0A RID: 2826
				private bool _hasRemoved;
			}

			// Token: 0x02000387 RID: 903
			private sealed class PeriodicTimer : IDisposable
			{
				// Token: 0x06001261 RID: 4705 RVA: 0x00053688 File Offset: 0x00051A88
				public PeriodicTimer(TimeSpan period, Action action)
				{
					this._action = action;
					this._timer = new System.Threading.Timer(new TimerCallback(this.Tick), null, period, period);
					this._gate = new AsyncLock();
					object obj = Scheduler.ThreadPoolScheduler.PeriodicTimer.s_timers;
					lock (obj)
					{
						Scheduler.ThreadPoolScheduler.PeriodicTimer.s_timers.Add(this._timer);
					}
				}

				// Token: 0x06001262 RID: 4706 RVA: 0x00053700 File Offset: 0x00051B00
				private void Tick(object state)
				{
					this._gate.Wait(delegate
					{
						this._action();
					});
				}

				// Token: 0x06001263 RID: 4707 RVA: 0x0005371C File Offset: 0x00051B1C
				public void Dispose()
				{
					System.Threading.Timer timer = null;
					object obj = Scheduler.ThreadPoolScheduler.PeriodicTimer.s_timers;
					lock (obj)
					{
						timer = this._timer;
						this._timer = null;
						if (timer != null)
						{
							Scheduler.ThreadPoolScheduler.PeriodicTimer.s_timers.Remove(timer);
						}
					}
					if (timer != null)
					{
						timer.Dispose();
						this._action = Stubs.Nop;
					}
				}

				// Token: 0x04000B0B RID: 2827
				private static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();

				// Token: 0x04000B0C RID: 2828
				private Action _action;

				// Token: 0x04000B0D RID: 2829
				private System.Threading.Timer _timer;

				// Token: 0x04000B0E RID: 2830
				private readonly AsyncLock _gate;
			}
		}

		// Token: 0x020003D1 RID: 977
		private class MainThreadScheduler : IScheduler, ISchedulerPeriodic, ISchedulerQueueing
		{
			// Token: 0x060013F8 RID: 5112 RVA: 0x000537F5 File Offset: 0x00051BF5
			public MainThreadScheduler()
			{
				MainThreadDispatcher.Initialize();
				this.scheduleAction = new Action<object>(this.Schedule);
			}

			// Token: 0x060013F9 RID: 5113 RVA: 0x00053814 File Offset: 0x00051C14
			private IEnumerator DelayAction(TimeSpan dueTime, Action action, ICancelable cancellation)
			{
				if (dueTime == TimeSpan.Zero)
				{
					yield return null;
				}
				else
				{
					yield return new WaitForSeconds((float)dueTime.TotalSeconds);
				}
				if (cancellation.IsDisposed)
				{
					yield break;
				}
				MainThreadDispatcher.UnsafeSend(action);
				yield break;
			}

			// Token: 0x060013FA RID: 5114 RVA: 0x00053840 File Offset: 0x00051C40
			private IEnumerator PeriodicAction(TimeSpan period, Action action, ICancelable cancellation)
			{
				if (period == TimeSpan.Zero)
				{
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						MainThreadDispatcher.UnsafeSend(action);
					}
					yield break;
				}
				float seconds = (float)(period.TotalMilliseconds / 1000.0);
				WaitForSeconds yieldInstruction = new WaitForSeconds(seconds);
				for (;;)
				{
					yield return yieldInstruction;
					if (cancellation.IsDisposed)
					{
						break;
					}
					MainThreadDispatcher.UnsafeSend(action);
				}
				yield break;
				yield break;
			}

			// Token: 0x1700016D RID: 365
			// (get) Token: 0x060013FB RID: 5115 RVA: 0x00053869 File Offset: 0x00051C69
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x060013FC RID: 5116 RVA: 0x00053870 File Offset: 0x00051C70
			private void Schedule(object state)
			{
				Tuple<BooleanDisposable, Action> tuple = (Tuple<BooleanDisposable, Action>)state;
				if (!tuple.Item1.IsDisposed)
				{
					tuple.Item2();
				}
			}

			// Token: 0x060013FD RID: 5117 RVA: 0x000538A4 File Offset: 0x00051CA4
			public IDisposable Schedule(Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				MainThreadDispatcher.Post(this.scheduleAction, Tuple.Create<BooleanDisposable, Action>(booleanDisposable, action));
				return booleanDisposable;
			}

			// Token: 0x060013FE RID: 5118 RVA: 0x000538CF File Offset: 0x00051CCF
			public IDisposable Schedule(DateTimeOffset dueTime, Action action)
			{
				return this.Schedule(dueTime - this.Now, action);
			}

			// Token: 0x060013FF RID: 5119 RVA: 0x000538E4 File Offset: 0x00051CE4
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan dueTime2 = Scheduler.Normalize(dueTime);
				MainThreadDispatcher.SendStartCoroutine(this.DelayAction(dueTime2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x06001400 RID: 5120 RVA: 0x00053910 File Offset: 0x00051D10
			public IDisposable SchedulePeriodic(TimeSpan period, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan period2 = Scheduler.Normalize(period);
				MainThreadDispatcher.SendStartCoroutine(this.PeriodicAction(period2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x06001401 RID: 5121 RVA: 0x0005393C File Offset: 0x00051D3C
			private void ScheduleQueueing<T>(object state)
			{
				Tuple<ICancelable, T, Action<T>> tuple = (Tuple<ICancelable, T, Action<T>>)state;
				if (!tuple.Item1.IsDisposed)
				{
					tuple.Item3(tuple.Item2);
				}
			}

			// Token: 0x06001402 RID: 5122 RVA: 0x00053974 File Offset: 0x00051D74
			public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
			{
				MainThreadDispatcher.Post(Scheduler.MainThreadScheduler.QueuedAction<T>.Instance, Tuple.Create<ICancelable, T, Action<T>>(cancel, state, action));
			}

			// Token: 0x04000BA1 RID: 2977
			private readonly Action<object> scheduleAction;

			// Token: 0x020003D2 RID: 978
			private static class QueuedAction<T>
			{
				// Token: 0x06001403 RID: 5123 RVA: 0x00053990 File Offset: 0x00051D90
				public static void Invoke(object state)
				{
					Tuple<ICancelable, T, Action<T>> tuple = (Tuple<ICancelable, T, Action<T>>)state;
					if (!tuple.Item1.IsDisposed)
					{
						tuple.Item3(tuple.Item2);
					}
				}

				// Token: 0x04000BA2 RID: 2978
				public static readonly Action<object> Instance = new Action<object>(Scheduler.MainThreadScheduler.QueuedAction<T>.Invoke);
			}
		}

		// Token: 0x020003D3 RID: 979
		private class IgnoreTimeScaleMainThreadScheduler : IScheduler, ISchedulerPeriodic, ISchedulerQueueing
		{
			// Token: 0x06001405 RID: 5125 RVA: 0x00053BFA File Offset: 0x00051FFA
			public IgnoreTimeScaleMainThreadScheduler()
			{
				MainThreadDispatcher.Initialize();
				this.scheduleAction = new Action<object>(this.Schedule);
			}

			// Token: 0x06001406 RID: 5126 RVA: 0x00053C1C File Offset: 0x0005201C
			private IEnumerator DelayAction(TimeSpan dueTime, Action action, ICancelable cancellation)
			{
				if (dueTime == TimeSpan.Zero)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						yield break;
					}
					MainThreadDispatcher.UnsafeSend(action);
				}
				else
				{
					float elapsed = 0f;
					float dt = (float)dueTime.TotalSeconds;
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						elapsed += Time.unscaledDeltaTime;
						if (elapsed >= dt)
						{
							goto Block_4;
						}
					}
					goto IL_FF;
					Block_4:
					MainThreadDispatcher.UnsafeSend(action);
				}
				IL_FF:
				yield break;
			}

			// Token: 0x06001407 RID: 5127 RVA: 0x00053C48 File Offset: 0x00052048
			private IEnumerator PeriodicAction(TimeSpan period, Action action, ICancelable cancellation)
			{
				if (period == TimeSpan.Zero)
				{
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						MainThreadDispatcher.UnsafeSend(action);
					}
					yield break;
				}
				float elapsed = 0f;
				float dt = (float)period.TotalSeconds;
				for (;;)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						break;
					}
					elapsed += Time.unscaledDeltaTime;
					if (elapsed >= dt)
					{
						MainThreadDispatcher.UnsafeSend(action);
						elapsed = 0f;
					}
				}
				yield break;
			}

			// Token: 0x1700016E RID: 366
			// (get) Token: 0x06001408 RID: 5128 RVA: 0x00053C71 File Offset: 0x00052071
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x06001409 RID: 5129 RVA: 0x00053C78 File Offset: 0x00052078
			private void Schedule(object state)
			{
				Tuple<BooleanDisposable, Action> tuple = (Tuple<BooleanDisposable, Action>)state;
				if (!tuple.Item1.IsDisposed)
				{
					tuple.Item2();
				}
			}

			// Token: 0x0600140A RID: 5130 RVA: 0x00053CAC File Offset: 0x000520AC
			public IDisposable Schedule(Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				MainThreadDispatcher.Post(this.scheduleAction, Tuple.Create<BooleanDisposable, Action>(booleanDisposable, action));
				return booleanDisposable;
			}

			// Token: 0x0600140B RID: 5131 RVA: 0x00053CD7 File Offset: 0x000520D7
			public IDisposable Schedule(DateTimeOffset dueTime, Action action)
			{
				return this.Schedule(dueTime - this.Now, action);
			}

			// Token: 0x0600140C RID: 5132 RVA: 0x00053CEC File Offset: 0x000520EC
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan dueTime2 = Scheduler.Normalize(dueTime);
				MainThreadDispatcher.SendStartCoroutine(this.DelayAction(dueTime2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x0600140D RID: 5133 RVA: 0x00053D18 File Offset: 0x00052118
			public IDisposable SchedulePeriodic(TimeSpan period, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan period2 = Scheduler.Normalize(period);
				MainThreadDispatcher.SendStartCoroutine(this.PeriodicAction(period2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x0600140E RID: 5134 RVA: 0x00053D41 File Offset: 0x00052141
			public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
			{
				MainThreadDispatcher.Post(Scheduler.IgnoreTimeScaleMainThreadScheduler.QueuedAction<T>.Instance, Tuple.Create<ICancelable, T, Action<T>>(cancel, state, action));
			}

			// Token: 0x04000BA3 RID: 2979
			private readonly Action<object> scheduleAction;

			// Token: 0x020003D4 RID: 980
			private static class QueuedAction<T>
			{
				// Token: 0x0600140F RID: 5135 RVA: 0x00053D5C File Offset: 0x0005215C
				public static void Invoke(object state)
				{
					Tuple<ICancelable, T, Action<T>> tuple = (Tuple<ICancelable, T, Action<T>>)state;
					if (!tuple.Item1.IsDisposed)
					{
						tuple.Item3(tuple.Item2);
					}
				}

				// Token: 0x04000BA4 RID: 2980
				public static readonly Action<object> Instance = new Action<object>(Scheduler.IgnoreTimeScaleMainThreadScheduler.QueuedAction<T>.Invoke);
			}
		}

		// Token: 0x020003D5 RID: 981
		private class FixedUpdateMainThreadScheduler : IScheduler, ISchedulerPeriodic, ISchedulerQueueing
		{
			// Token: 0x06001411 RID: 5137 RVA: 0x0005403B File Offset: 0x0005243B
			public FixedUpdateMainThreadScheduler()
			{
				MainThreadDispatcher.Initialize();
			}

			// Token: 0x06001412 RID: 5138 RVA: 0x00054048 File Offset: 0x00052448
			private IEnumerator ImmediateAction<T>(T state, Action<T> action, ICancelable cancellation)
			{
				yield return null;
				if (cancellation.IsDisposed)
				{
					yield break;
				}
				MainThreadDispatcher.UnsafeSend<T>(action, state);
				yield break;
			}

			// Token: 0x06001413 RID: 5139 RVA: 0x00054074 File Offset: 0x00052474
			private IEnumerator DelayAction(TimeSpan dueTime, Action action, ICancelable cancellation)
			{
				if (dueTime == TimeSpan.Zero)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						yield break;
					}
					MainThreadDispatcher.UnsafeSend(action);
				}
				else
				{
					float startTime = Time.fixedTime;
					float dt = (float)dueTime.TotalSeconds;
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						float elapsed = Time.fixedTime - startTime;
						if (elapsed >= dt)
						{
							goto Block_4;
						}
					}
					goto IL_FF;
					Block_4:
					MainThreadDispatcher.UnsafeSend(action);
				}
				IL_FF:
				yield break;
			}

			// Token: 0x06001414 RID: 5140 RVA: 0x000540A0 File Offset: 0x000524A0
			private IEnumerator PeriodicAction(TimeSpan period, Action action, ICancelable cancellation)
			{
				if (period == TimeSpan.Zero)
				{
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						MainThreadDispatcher.UnsafeSend(action);
					}
					yield break;
				}
				float startTime = Time.fixedTime;
				float dt = (float)period.TotalSeconds;
				for (;;)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						break;
					}
					float ft = Time.fixedTime;
					float elapsed = ft - startTime;
					if (elapsed >= dt)
					{
						MainThreadDispatcher.UnsafeSend(action);
						startTime = ft;
					}
				}
				yield break;
			}

			// Token: 0x1700016F RID: 367
			// (get) Token: 0x06001415 RID: 5141 RVA: 0x000540C9 File Offset: 0x000524C9
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x06001416 RID: 5142 RVA: 0x000540D0 File Offset: 0x000524D0
			public IDisposable Schedule(Action action)
			{
				return this.Schedule(TimeSpan.Zero, action);
			}

			// Token: 0x06001417 RID: 5143 RVA: 0x000540DE File Offset: 0x000524DE
			public IDisposable Schedule(DateTimeOffset dueTime, Action action)
			{
				return this.Schedule(dueTime - this.Now, action);
			}

			// Token: 0x06001418 RID: 5144 RVA: 0x000540F4 File Offset: 0x000524F4
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan dueTime2 = Scheduler.Normalize(dueTime);
				MainThreadDispatcher.StartFixedUpdateMicroCoroutine(this.DelayAction(dueTime2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x06001419 RID: 5145 RVA: 0x00054120 File Offset: 0x00052520
			public IDisposable SchedulePeriodic(TimeSpan period, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan period2 = Scheduler.Normalize(period);
				MainThreadDispatcher.StartFixedUpdateMicroCoroutine(this.PeriodicAction(period2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x0600141A RID: 5146 RVA: 0x00054149 File Offset: 0x00052549
			public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
			{
				MainThreadDispatcher.StartFixedUpdateMicroCoroutine(this.ImmediateAction<T>(state, action, cancel));
			}
		}

		// Token: 0x020003D6 RID: 982
		private class EndOfFrameMainThreadScheduler : IScheduler, ISchedulerPeriodic, ISchedulerQueueing
		{
			// Token: 0x0600141B RID: 5147 RVA: 0x000544A4 File Offset: 0x000528A4
			public EndOfFrameMainThreadScheduler()
			{
				MainThreadDispatcher.Initialize();
			}

			// Token: 0x0600141C RID: 5148 RVA: 0x000544B4 File Offset: 0x000528B4
			private IEnumerator ImmediateAction<T>(T state, Action<T> action, ICancelable cancellation)
			{
				yield return null;
				if (cancellation.IsDisposed)
				{
					yield break;
				}
				MainThreadDispatcher.UnsafeSend<T>(action, state);
				yield break;
			}

			// Token: 0x0600141D RID: 5149 RVA: 0x000544E0 File Offset: 0x000528E0
			private IEnumerator DelayAction(TimeSpan dueTime, Action action, ICancelable cancellation)
			{
				if (dueTime == TimeSpan.Zero)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						yield break;
					}
					MainThreadDispatcher.UnsafeSend(action);
				}
				else
				{
					float elapsed = 0f;
					float dt = (float)dueTime.TotalSeconds;
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						elapsed += Time.deltaTime;
						if (elapsed >= dt)
						{
							goto Block_4;
						}
					}
					goto IL_FF;
					Block_4:
					MainThreadDispatcher.UnsafeSend(action);
				}
				IL_FF:
				yield break;
			}

			// Token: 0x0600141E RID: 5150 RVA: 0x0005450C File Offset: 0x0005290C
			private IEnumerator PeriodicAction(TimeSpan period, Action action, ICancelable cancellation)
			{
				if (period == TimeSpan.Zero)
				{
					for (;;)
					{
						yield return null;
						if (cancellation.IsDisposed)
						{
							break;
						}
						MainThreadDispatcher.UnsafeSend(action);
					}
					yield break;
				}
				float elapsed = 0f;
				float dt = (float)period.TotalSeconds;
				for (;;)
				{
					yield return null;
					if (cancellation.IsDisposed)
					{
						break;
					}
					elapsed += Time.deltaTime;
					if (elapsed >= dt)
					{
						MainThreadDispatcher.UnsafeSend(action);
						elapsed = 0f;
					}
				}
				yield break;
			}

			// Token: 0x17000170 RID: 368
			// (get) Token: 0x0600141F RID: 5151 RVA: 0x00054535 File Offset: 0x00052935
			public DateTimeOffset Now
			{
				get
				{
					return Scheduler.Now;
				}
			}

			// Token: 0x06001420 RID: 5152 RVA: 0x0005453C File Offset: 0x0005293C
			public IDisposable Schedule(Action action)
			{
				return this.Schedule(TimeSpan.Zero, action);
			}

			// Token: 0x06001421 RID: 5153 RVA: 0x0005454A File Offset: 0x0005294A
			public IDisposable Schedule(DateTimeOffset dueTime, Action action)
			{
				return this.Schedule(dueTime - this.Now, action);
			}

			// Token: 0x06001422 RID: 5154 RVA: 0x00054560 File Offset: 0x00052960
			public IDisposable Schedule(TimeSpan dueTime, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan dueTime2 = Scheduler.Normalize(dueTime);
				MainThreadDispatcher.StartEndOfFrameMicroCoroutine(this.DelayAction(dueTime2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x06001423 RID: 5155 RVA: 0x0005458C File Offset: 0x0005298C
			public IDisposable SchedulePeriodic(TimeSpan period, Action action)
			{
				BooleanDisposable booleanDisposable = new BooleanDisposable();
				TimeSpan period2 = Scheduler.Normalize(period);
				MainThreadDispatcher.StartEndOfFrameMicroCoroutine(this.PeriodicAction(period2, action, booleanDisposable));
				return booleanDisposable;
			}

			// Token: 0x06001424 RID: 5156 RVA: 0x000545B5 File Offset: 0x000529B5
			public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
			{
				MainThreadDispatcher.StartEndOfFrameMicroCoroutine(this.ImmediateAction<T>(state, action, cancel));
			}
		}
	}
}
